 #ifndef _GCHRONO_H_
#define _GCHRONO_H_

#include <unistd.h> 
#include <ctime>

#ifdef GMPI
#include <mpi.h>
#endif


inline double gtime() {
#ifdef GMPI
  return MPI_Wtime() ;
#else
  return (double)clock() / (double)CLOCKS_PER_SEC ;
#endif

}


/**
 * A chrono to measure the time elapse in seconds
 */
class gchrono {
 private:
  /* clock_t cpuStart, cpuStop ; */
  /* clock_t totalTime ; */
  double cpuStart, cpuStop ;
  double totalTime ;

 public:
    gchrono(){totalTime = 0 ;}

    inline void reset() {totalTime = 0 ;}

    inline virtual void start() { cpuStart = gtime() ; }
    inline virtual void stop() { cpuStop = gtime() ; totalTime += cpuStop - cpuStart ; }
    inline double getRunningTime() { return gtime() - cpuStart ; }
    inline double getTotalTime() { return totalTime ; }
    inline double getTotalTimeSec() { return totalTime ; }
    inline double getTotalTimeMs() { return (double)1000.0*totalTime ; }
    inline double getStopTimeMs() { return (double)1000.0*cpuStop ; }
} ;




/**
 * A chrono to measure the time elapse in milliseconds
 */
class gchronoms {
 private:
  clock_t cpuStart, cpuStop ; 
  clock_t totalTime ; 

 public:
    gchronoms(){totalTime = 0 ;}

    inline void reset() {totalTime = 0 ;}

    inline void start() { cpuStart = clock() ; }
    inline void stop() { cpuStop = clock() ; totalTime += cpuStop - cpuStart ; }
    inline long getTotalTime() { return (long)totalTime ; }
    inline long getTotalTimeSec() { return (long)totalTime / (long)CLOCKS_PER_SEC ; }
    inline long getTotalTimeMs() { return (long)1000*(long)totalTime / (long)CLOCKS_PER_SEC ; }
    inline long getStopTimeMs() { return (long)1000*(long)cpuStop / (long)CLOCKS_PER_SEC ; }
} ;




/**
 * A alarm in seconds
 */
class galarm {
 private:
  // for alarm
  double delay ;
  double alarm ;


 public:
    galarm(){}

    inline void setAlarmDuration(double s) { delay = s ; rearm() ;}
    inline double getAlarmDuration() {return delay ;}
    inline void rearm() {alarm = gtime() + delay ;}

    /**
     * @return 1 if the alarm triggers, 0 otherwise
     */ 
    inline int testAndRearmAlarm() {
      if (gtime()>alarm) { rearm() ; return 1 ;}
      return 0 ;
    }
} ;

#endif
